#include <stdexcept>
#include "mainwindow.h"
#include "connectiondialog.h"
#include "databaseexplorermodel.h"
#include "bsonexplorermodel.h"
#include "bsonlistmodel.h"
#include "bsonexplorermodel.h"
#include "serveroverviewwidget.h"
#include "adddatabasedialog.h"
#include "editcollectionwidget.h"
#include "databaseoverviewwidget.h"
#include "profilingleveldialog.h"
#include "preferencesdialog.h"
#include "preferences.h"
#include <Qsci/qsciscintilla.h>
#include "utils.h"
#include "jseditor.h"
#include "mapreducewidget.h"
#include "adduserwidget.h"
#include "bsontableviewwidget.h"
#include "shardingwidget.h"
#include "aggregatoinwidget.h"
#include "dbconnection.h"
#include "dbconnectionmanager.h"
#include <client/connpool.h>
using namespace mongo;

using namespace std;
QListWidget* MainWindow::pTraceList=NULL;

MainWindow::MainWindow()
{
#if QT_VERSION < 0x040500
    if(Preferences::instance()->checkQtVersion())
    {
        QMessageBox::warning(this,tr("Mongodb Client"),
           tr("Mongodb Client is using Qt %1. Some features will be disabled.").arg(qVersion()));
    }
#endif

    databaseExplorerModel=new DatabaseExplorerModel(this);
    databaseExplorerView=new QTreeView();
    databaseExplorerView->setModel(databaseExplorerModel);

    databaseExplorerDockPane=new QDockWidget(tr("Database Explorer"),this);
    databaseExplorerDockPane->setObjectName("databaseExplorerDockPane");
    databaseExplorerDockPane->setWidget(databaseExplorerView);
    databaseExplorerDockPane->setAllowedAreas(Qt::AllDockWidgetAreas);
    addDockWidget(Qt::LeftDockWidgetArea,databaseExplorerDockPane);

    bsonExplorerDockPane=NULL;

    commandShow=new QListWidget();
    commandShowDockPane=new QDockWidget(tr("Command Show"),this);
    commandShowDockPane->setObjectName("commandShowDockPane");
    commandShowDockPane->setWidget(commandShow);
    commandShowDockPane->setAllowedAreas(Qt::AllDockWidgetAreas);
    addDockWidget(Qt::BottomDockWidgetArea,commandShowDockPane);
    connectionDialog=NULL;

    centerTabViews=new QTabWidget();
    //
#if QT_VERSION > 0x040500
    centerTabViews->setTabsClosable(true);
    centerTabViews->setUsesScrollButtons(true);
    centerTabViews->setMovable(true);
    connect(centerTabViews,SIGNAL(tabCloseRequested(int)),this,SLOT(closeTabWindow(int)));
#endif
    setCentralWidget(centerTabViews);

    clientConnection=NULL;
    serverOverview=NULL;
    editCollection=NULL;
    bsonListModel=NULL;
    bsonListView=NULL;
    javaScriptEditor=NULL;
    mapReduceWidget=NULL;
    gridFS=NULL;
    createActions();
    createMenus();
    createToolBars();

    createStatusBar();

    readSettings();
    setWindowIcon(QIcon(":/images/icon.png"));
    //setCurrentFile("");
    if(NULL==pTraceList)
    {
        pTraceList=this->commandShow;
    }
    connect(
            databaseExplorerView,
            SIGNAL(pressed(const QModelIndex&)),
            this,
            SLOT(SlotItemClicked(const QModelIndex&))
            );
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(okToContinue()){
        writeSettings();
        event->accept();
    }else{
        event->ignore();
    }
}

MainWindow *MainWindow::getInstance()
{
    if(NULL==pInstance)
    {
        pInstance=new MainWindow;
    }
    return pInstance;
}


void MainWindow::createActions()
{
    addConnectionAction=new QAction(tr("&Connection"),this);
    addConnectionAction->setIcon(QIcon(":/images/addConnectionAction.png"));
    addConnectionAction->setShortcut(QKeySequence::New);
    addConnectionAction->setStatusTip(tr("Create a new MongoDB connection"));
    connect(addConnectionAction,SIGNAL(triggered()),this,SLOT(addConnectionResponse()));

    exitAction=new QAction(tr("E&xit"),this);
    exitAction->setIcon(QIcon(":/images/exitAction.png"));
    exitAction->setShortcut(tr("Ctrl+Q"));
    exitAction->setStatusTip(tr("Exit the application"));
    connect(exitAction,SIGNAL(triggered()),this,SLOT(close()));

    serverOverviewAction = new QAction(tr("&Overview"), this);
    serverOverviewAction->setIcon(QIcon(":/images/serverOverviewAction.png"));
    serverOverviewAction->setShortcut(tr("Ctrl+Alt+S"));
    serverOverviewAction->setStatusTip(tr("Overview the server..."));
    connect(serverOverviewAction, SIGNAL(triggered()), this, SLOT(serverOverviewResponse()));

    addDatabaseAction = new QAction(tr("&Add Database"), this);
    addDatabaseAction->setIcon(QIcon(":/images/addDatabaseAction.png"));
    addDatabaseAction->setShortcut(tr("Ctrl+Alt+A"));
    addDatabaseAction->setStatusTip(tr("Add a database"));
    connect(addDatabaseAction, SIGNAL(triggered()), this, SLOT(addDatabaseResponse()));

    disconnectAction = new QAction(tr("Disconnect"), this);
    //disconnectAction->setIcon(QIcon(":/images/disconnectAction.png"));
    disconnectAction->setStatusTip(tr("Disconnect current database"));
    //connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectResponse()));

    serverStatusAction=new QAction(tr("Status"),this);
    serverStatusAction->setIcon(QIcon(":/images/statusAction.png"));
    serverStatusAction->setShortcut(tr("Ctrl+Shift+S"));
    serverStatusAction->setStatusTip(tr("report for this server status"));
    connect(serverStatusAction,SIGNAL(triggered()),this,SLOT());

    databaseOverViewAction=new QAction(tr("Over View"),this);
    databaseOverViewAction->setIcon(QIcon(":/images/databaseOverviewAction.png"));
    databaseOverViewAction->setStatusTip(tr("Over View this database"));
    connect(databaseOverViewAction,SIGNAL(triggered()),this,SLOT(databaseOverViewResponse()));

    profilingLevelAction=new QAction(tr("&Profiling Level"),this);
    profilingLevelAction->setIcon(QIcon(":/images/profilingLevelAction.png"));
    profilingLevelAction->setStatusTip(tr("edit profile database level"));
    connect(profilingLevelAction,SIGNAL(triggered()),this,SLOT(doProfilingLevel()));

    addDatabaseConnectionAction=new QAction(tr("&Add Connection"),this);
    addDatabaseConnectionAction->setIcon(QIcon(":/images/addDatabaseConnectionAction.png"));
    addDatabaseConnectionAction->setStatusTip(tr("add a new connection to database"));

    addJavascriptAction=new QAction(tr("&Add Javascript"),this);
    addJavascriptAction->setIcon(QIcon(":/images/addJavascriptAction.png"));
    addJavascriptAction->setStatusTip(tr("add a stored javascript file to database"));

    importAction=new QAction(tr("&Import"),this);
    importAction->setIcon(QIcon(":/images/importAction.png"));
    importAction->setStatusTip(tr("import data from mysql server"));

    copyCollections2Other=new QAction(tr("&Copy Collections to Other"),this);
    copyCollections2Other->setIcon(QIcon(":/images/copyCollections2Other.png"));
    copyCollections2Other->setStatusTip(tr("copy collection to other server"));


    dropDatabaseAction=new QAction(tr("&Drop Database"),this);
    dropDatabaseAction->setIcon(QIcon(":/images/dropDatabaseAction.png"));
    dropDatabaseAction->setStatusTip(tr("drop selected database"));

    statsDatabaseAction=new QAction(tr("&Stats Database"),this);
    statsDatabaseAction->setIcon(QIcon(":/images/statsDatabaseAction.png"));
    statsDatabaseAction->setStatusTip(tr("stats selected database"));

    viewAction=new QAction(tr("&View"),this);
    viewAction->setIcon(QIcon(":/images/viewAction.png"));
    viewAction->setShortcut(tr("Ctrl+Alt+V"));
    viewAction->setStatusTip(tr("View this collection"));
    connect(viewAction,SIGNAL(triggered()),this,SLOT(viewDataResponse()));

    findAction=new QAction(tr("&Find"),this);
    findAction->setIcon(QIcon(":/images/findAction.png"));
    findAction->setShortcut(QKeySequence::Find);
    findAction->setStatusTip(tr("find string in this collection"));
    //connect(pasteAction,SIGNAL(triggered()),spreadsheet,SLOT(paste()));

    find2Action = new QAction(tr("&Find2"), this);
    find2Action->setShortcut(tr("Ctrl+Shift+F"));
    find2Action->setIcon(QIcon(":/images/find2Action.png"));
    find2Action->setStatusTip(tr("Find other int this collection"));
    //connect(deleteAction, SIGNAL(triggered()),spreadsheet, SLOT(del()));

    updateAction = new QAction(tr("&Update"), this);
    updateAction->setIcon(QIcon(":/images/updateAction.png"));
    updateAction->setStatusTip(tr("apply update in this collection"));
    //connect(selectRowAction, SIGNAL(triggered()),spreadsheet, SLOT(selectCurrentRow()));

    mapReduceAction = new QAction(tr("&MapReduce"), this);
    mapReduceAction->setIcon(QIcon(":/images/mapReduceAction.png"));
    mapReduceAction->setStatusTip(tr("use map reduce"));
    connect(mapReduceAction, SIGNAL(triggered()),this, SLOT(mapReduce()));


    insertCollectionAction=new QAction(tr("&Insert a collection"),this);
    insertCollectionAction->setIcon(QIcon(":/images/insertCollectionAction.png"));
    insertCollectionAction->setShortcut(tr("Ctrl+Alt+i"));
    insertCollectionAction->setStatusTip(tr("insert a new document in this collection"));
    connect(insertCollectionAction,SIGNAL(triggered()),this,SLOT(insertCollectionResponse()));//此处要修改

    addIndexAction=new QAction(tr("&Add Index"),this);
    addIndexAction->setIcon(QIcon(":/images/addIndexAction.png"));
    //addIndexAction->setShortcut(tr("Ctrl+G"));
    addIndexAction->setStatusTip(tr("add index for this collection"));

    duplicateCollection=new QAction(tr("&Duplicate Collection"),this);
    duplicateCollection->setIcon(QIcon(":/images/duplicateCollection.png"));
    //duplicateCollection->setShortcut(tr("F9"));
    duplicateCollection->setStatusTip(tr("duplicate this collection"));

    copyCollection2Other=new QAction(tr("&Copy Collection to Server"),this);
    copyCollection2Other->setIcon(QIcon(":/images/copyCollection2Other.png"));
    copyCollection2Other->setStatusTip(tr("Sort the selected cells or all the cells"));

    removeAction=new QAction(tr("&Remove"),this);
    removeAction->setIcon(QIcon(":/images/removeAction.png"));
    removeAction->setStatusTip(tr("remove document from collection"));

    removeAllAction=new QAction(tr("&Remove All"),this);
    removeAllAction->setIcon(QIcon(":/images/removeAllAction.png"));
    removeAllAction->setStatusTip(tr("remove all document from selected collection"));

    dropCollectionAction=new QAction(tr("&Drop Collection"),this);
    dropCollectionAction->setIcon(QIcon(":/images/dropCollectionAction.png"));
    dropCollectionAction->setStatusTip(tr("drop selected collection"));
    connect(dropCollectionAction,SIGNAL(triggered()),this,SLOT(dropCollectionResponse()));

    statsCollectionAction=new QAction(tr("&Stats Collection"),this);
    statsCollectionAction->setStatusTip(tr("stats the collection"));
    connect(statsCollectionAction,SIGNAL(triggered()),this,SLOT(collectionStatsResponse()));

    dropIndexAction=new QAction(tr("&Drop Index"),this);
    dropIndexAction->setIcon(QIcon(":/images/dropIndexAction.png"));
    dropIndexAction->setStatusTip(tr("Drop selected collection's index"));
    connect(dropIndexAction,SIGNAL(triggered()),this,SLOT(dropIndex()));

    propertiesAction=new QAction(tr("&Properties"),this);
    propertiesAction->setIcon(QIcon(":/images/propertiesAction.png"));
    propertiesAction->setStatusTip(tr("index properties"));
    //connect(autoRecalcAction,SIGNAL(toggled(bool)),spreadsheet,SLOT(setAutoRecalculate(bool)));

    editJavascriptAction=new QAction(tr("&Edit Javascript"),this);
    editJavascriptAction->setIcon(QIcon(":/images/editJavascriptAction.png"));
    editJavascriptAction->setStatusTip("Show the application's About box");
    connect(editJavascriptAction, SIGNAL(triggered()), this, SLOT(doEditJavaScriptResponse()));

    serverMonitoringAction=new QAction(tr("&Server Monitoring"),this);
    serverMonitoringAction->setIcon(QIcon(":/images/serverMonitoringAction.png"));
    serverMonitoringAction->setStatusTip(tr("Show the Qt library's About box"));
    //connect(aboutQtAction,SIGNAL(triggered()),qApp,SLOT(aboutQt()));

    shardingOptionsAction=new QAction(tr("Sharding Options"),this);
    connect(shardingOptionsAction,SIGNAL(triggered()),this,SLOT(shardingOptionsResponse()));

    aggretationAction=new QAction(tr("Aggretation"),this);
    connect(aggretationAction,SIGNAL(triggered()),this,SLOT(aggretationResponse()));

    preferencesAction=new QAction(tr("&Preferences"),this);
    preferencesAction->setIcon(QIcon(":/images/preferencesAction.png"));
    preferencesAction->setStatusTip(tr("edit application preferences"));
    connect(preferencesAction,SIGNAL(triggered()),this,SLOT(setPreferences()));

    closeAction=new QAction(tr("&Close"),this);
    closeAction->setIcon(QIcon(":/images/closeAction.png"));
    closeAction->setStatusTip(tr("close active window"));
    connect(closeAction,SIGNAL(triggered()),this,SLOT(closeActiveWindow()));

    closeAllAction=new QAction(tr("&Close All"),this);
    closeAllAction->setIcon(QIcon(":/images/closeAllAction.png"));
    closeAllAction->setStatusTip(tr("close all windows"));
    connect(closeAllAction,SIGNAL(triggered()),this,SLOT(closeAllWindows()));

    licenseManagerAction=new QAction(tr("&License Manager"),this);
    licenseManagerAction->setIcon(QIcon(":/images/licenseManagerAction.png"));
    licenseManagerAction->setStatusTip(tr("Manager licenses"));

    aboutAction=new QAction(tr("&About"),this);
    aboutAction->setIcon(QIcon(":/images/aboutAction.png"));
    aboutAction->setStatusTip(tr("about this application"));
    connect(aboutAction,SIGNAL(triggered()),this,SLOT(about()));

    addUserAction=new QAction(tr("Add User"),this);
    addUserAction->setIcon(QIcon(":/images/statsDatabaseAction.png"));
    addUserAction->setStatusTip(tr("Add User to database"));
    connect(addUserAction,SIGNAL(triggered()),this,SLOT(addUserResponse()));

    repairDatabaseAction=new QAction(tr("Repair Database"),this);
    repairDatabaseAction->setStatusTip(tr("Repair selected database"));
    connect(repairDatabaseAction,SIGNAL(triggered()),this,SLOT(repairDatabaseResponse()));


    restoreAction=new QAction(tr("Restore Database"),this);
    restoreAction->setStatusTip(tr("Restore selected database as it is"));

    initGFSAction=new QAction(tr("Init GFS"),this);
    initGFSAction->setStatusTip(tr("Init Grid File System"));

    closeServerAction=new QAction(tr("Close Server"),this);
    closeServerAction->setStatusTip(tr("Close selected server"));

    initReplicaAction=new QAction(tr("Init ReplicaSet"),this);
    initReplicaAction->setStatusTip(tr("Initialize a ReplicaSet from server"));

    setReplicaAction=new QAction(tr("Set ReplicaSet"),this);
    setReplicaAction->setStatusTip(tr("Set Option for the ReplicaSet"));

    setShardingAction=new QAction(tr("Set Sharding"),this);
    setShardingAction->setStatusTip(tr("Set Sharding for the server"));

    runJSAction=new QAction(tr("Run JavaScript"),this);
    runJSAction->setStatusTip(tr("Run JavaScript on the selected db"));

    renameCollectionAction=new QAction(tr("Rename Collection"),this);
    connect(renameCollectionAction,SIGNAL(triggered()),this,SLOT(renameCollectionResponse()));
    backupCollectionAction=new QAction(tr("Backup Collection"),this);
    importCollectionAction=new QAction(tr("Import Collection"),this);
    exportCollectionAction=new QAction(tr("Export Collection"),this);
    compactCollectionAction=new QAction(tr("Compact Collection"),this);
    indexManageAction=new QAction(tr("Compact Collection"),this);
    reIndexAction=new QAction(tr("reIndex"),this);
    restoreCollectionAction=new QAction(tr("Restore"),this);
}


void MainWindow::openRecentFile()
{
    if(okToContinue()){
        QAction* action=qobject_cast<QAction*>(sender());
        if(action){
            loadFile(action->data().toString());
        }
    }
}

void MainWindow::createMenus()
{
    fileMenu=menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(addConnectionAction);
    fileMenu->addAction(exitAction);


    serverMenu=menuBar()->addMenu(tr("&Server"));
    serverMenu->addAction(serverOverviewAction);
    serverMenu->addAction(addDatabaseAction);
    serverMenu->addAction(disconnectAction);
    serverMenu->addAction(statsDatabaseAction);

    databaseMenu=menuBar()->addMenu(tr("&Database"));
    databaseMenu->addAction(databaseOverViewAction);
    databaseMenu->addAction(profilingLevelAction);
    databaseMenu->addSeparator();
    databaseMenu->addAction(addConnectionAction);
    databaseMenu->addAction(addJavascriptAction);
    databaseMenu->addAction(importAction);
    databaseMenu->addAction(copyCollections2Other);
    databaseMenu->addSeparator();
    databaseMenu->addAction(dropDatabaseAction);
    databaseMenu->addAction(statsDatabaseAction);
    databaseMenu->addAction(addUserAction);


    collectionMenu=menuBar()->addMenu("&Collection");
    collectionMenu->addAction(viewAction);
    collectionMenu->addAction(findAction);
    collectionMenu->addAction(find2Action);
    collectionMenu->addAction(updateAction);
    collectionMenu->addAction(mapReduceAction);
    collectionMenu->addAction(insertCollectionAction);
    collectionMenu->addAction(addIndexAction);
    collectionMenu->addAction(duplicateCollection);
    collectionMenu->addAction(copyCollection2Other);
    collectionMenu->addAction(copyCollection2Other);
    collectionMenu->addAction(removeAction);
    collectionMenu->addAction(removeAllAction);
    collectionMenu->addAction(dropCollectionAction);
    collectionMenu->addAction(statsCollectionAction);

    qDebug("run here...");
    indexMenu=menuBar()->addMenu(tr("&Index"));
    indexMenu->addAction(dropIndexAction);
    indexMenu->addAction(propertiesAction);

    javascriptMenu=menuBar()->addMenu(tr("&Javascript"));
    javascriptMenu->addAction(editJavascriptAction);


    toolsMenu=menuBar()->addMenu(tr("&Tools"));
    toolsMenu->addAction(serverMonitoringAction);
    toolsMenu->addAction(preferencesAction);
    toolsMenu->addAction(shardingOptionsAction);
    toolsMenu->addAction(aggretationAction);

    windowMenu=menuBar()->addMenu(tr("&Window"));
    windowMenu->addAction(closeAction);
    windowMenu->addAction(closeAllAction);
    menuBar()->addSeparator();

    helpMenu=menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(licenseManagerAction);
    helpMenu->addAction(aboutAction);



}
void MainWindow::createToolBars()
{
    fileToolBar=addToolBar(tr("&File"));
    fileToolBar->addAction(addConnectionAction);
    fileToolBar->addAction(exitAction);


    databaseToolBar=addToolBar(tr("&Database"));
    databaseToolBar->addAction(databaseOverViewAction);
    databaseToolBar->addAction(profilingLevelAction);
    databaseToolBar->addAction(addDatabaseConnectionAction);
    databaseToolBar->addAction(importAction);
    databaseToolBar->addAction(dropDatabaseAction);

    collectionToolBar=addToolBar(tr("&Collection"));
    collectionToolBar->addAction(viewAction);
    collectionToolBar->addAction(updateAction);
    collectionToolBar->addAction(mapReduceAction);
    collectionToolBar->addAction(duplicateCollection);
}

void MainWindow::createStatusBar()
{
    locationLabel=new QLabel("Ready");
    locationLabel->setAlignment(Qt::AlignHCenter);
    locationLabel->setMinimumSize(locationLabel->sizeHint());

    formulaLabel=new QLabel;
    formulaLabel->setIndent(3);
    statusBar()->addWidget(locationLabel);
    statusBar()->addWidget(formulaLabel,1);
    updateStatusBar();
}

void MainWindow::updateStatusBar()
{
    //    locationLabel->setText(spreadsheet->currentLocation());
    //    formulaLabel->setText(spreadsheet->currentFormula());
}

void MainWindow::spreadsheetModified()
{
    setWindowModified(true);
    updateStatusBar();
}

void MainWindow::selectAll()
{
}

bool MainWindow::save()
{
    if(curFile.isEmpty()){
        return saveAs();
    }else{
        return saveFile(curFile);
    }
}
bool MainWindow::saveAs()
{
    QString fileName=QFileDialog::getSaveFileName(this,tr("Save Spreadsheet"),".",tr("Spreadsheet files(*.sp)"));
    if(fileName.isEmpty())
        return false;
    return saveFile(fileName);
}

void MainWindow::writeSettings()
{
    QSettings settings(Preferences::instance()->getCompanyName(),
                       Preferences::instance()->getAppName());
    settings.setValue("geometry",saveGeometry());
    settings.setValue("recentFiles",recentFiles);
}

void MainWindow::readSettings()
{
    QSettings settings(Preferences::instance()->getCompanyName(),
                       Preferences::instance()->getAppName());
    restoreGeometry(settings.value("geometry").toByteArray());
    recentFiles=settings.value("recentFiles").toStringList();
}

void MainWindow::setCurrentFile(const QString &fileName)
{
    curFile=fileName;
    setWindowModified(false);
    QString shownName=tr("Untitled");
    if(!curFile.isEmpty()){
        shownName=strippedName(curFile);
        recentFiles.removeAll(curFile);
        recentFiles.prepend(curFile);
        updateRecentFileActions();
    }
    setWindowTitle(tr("%1[*]-%2").arg(shownName).arg(tr("Spreadsheet")));
}

void MainWindow::about()
{
    QMessageBox::about(this, tr("About MongoDB_Client"),
                       tr("<h2>MongoDB_Client 1.1</h2>"
                          "<p>Copyright &copy; 2012 Software Inc."
                          "<p>MongoDB_Client is a small application that "
                          "manage for mongodb administrator cross platform! "
                          "Welcome to contract me mailto:rmb338@sina.com for any bugs!"));
}

void MainWindow::createContextMenu()
{
    //    spreadsheet->addAction(cutAction);
    //    spreadsheet->addAction(copyAction);
    //    spreadsheet->addAction(pasteAction);

    //    spreadsheet->setContextMenuPolicy(Qt::ActionsContextMenu);
}
bool MainWindow::okToContinue()
{
    if(isWindowModified()){
        int r=QMessageBox::warning(this,tr("Spreadsheet"),tr("The document has been modified.\n"
                                                             "Do you want to save your changes?"),
                                   QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
        if(r==QMessageBox::Yes){
            return save();
        }else if(r==QMessageBox::Cancel){
            return false;
        }
    }
    return true;
}

bool MainWindow::loadFile(const QString &fileName)
{
    //    if(!spreadsheet->readFile(fileName)){
    //        statusBar()->showMessage(tr("Loading canceled"),2000);
    //        return false;
    //    }
    setCurrentFile(fileName);
    return true;
}

bool MainWindow::saveFile(const QString &fileName)
{
    setCurrentFile(fileName);
    statusBar()->showMessage(tr("File saved"),2000);
    return true;
}

QString MainWindow::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

void MainWindow::updateRecentFileActions()
{
//    QMutableStringListIterator i(recentFiles);
//    while(i.hasNext()){
//        if(QFile::exists(i.next()))
//            i.remove();
//    }
//    for(int j=0;j<MaxRecentFiles;++j){
//        if(j<recentFiles.count()){
//            QString text=tr("&%1 %2").arg(j+1).arg(strippedName(recentFiles[j]));
//            recentFileActions[j]->setText(text);
//            recentFileActions[j]->setData(recentFiles[j]);
//            recentFileActions[j]->setVisible(true);
//        }else{
//            recentFileActions[j]->setVisible(false);
//        }
//    }
//    separatorAction->setVisible(!recentFiles.isEmpty());
}



void MainWindow::addConnectionResponse()
{
    if(!connectionDialog){
        connectionDialog=new ConnectionDialog(this);
        connect(connectionDialog,SIGNAL(requestConnectParamater(QString,DBClientConnection*)),
                this,SLOT(responseConnection(QString,DBClientConnection*)));
    }
    connectionDialog->show();
    connectionDialog->raise();
    connectionDialog->activateWindow();
}



void MainWindow::responseConnection(QString connectName,DBClientConnection *clientConnect)
{
    clientConnection=clientConnect;
    DBConnectionManager* pConnectManager=DBConnectionManager::getInstance();
    pConnectManager->addConnection(connectName.toStdString(),clientConnect);
    Node* root=new Node(Node::Connection,connectName);
    //if(replicaSet==NULL)
    {
        //ReplicaSetMonitorWatcher watcher=new ReplicaSetMonitorWatcher();
        string host=clientConnect->getServerAddress();
        HostAndPort hap(host);
        mongo::ConnectionString connStr(hap);
        string errmsg;
       replicaSet=(DBClientReplicaSet*)connStr.connect(errmsg);
       cout << "\t B " << replicaSet->findOne( "admin" , BSONObj() , 0 , QueryOption_SlaveOk ) << endl;
    }
    databaseExplorerModel->buildChildNodes(root,*clientConnection);
    connect(databaseExplorerView,SIGNAL(clicked(QModelIndex)),this,SLOT(selectedDatabaseChanged()));

}
/*
 * \remark server action function start
 *
 *
 *
 */
// show os info and build info
void MainWindow::serverOverviewResponse()
{
    if(!serverOverview)
    {
        serverOverview=new ServerOverviewWidget(this);
        //connect(serverOverviewAction,SIGNAL(triggered()),serverOverview,SLOT(initServerOverview(DBClientConnection&)));
    }
    //serverOverview->show();
    //serverOverview->raise();
    //serverOverview->activateWindow();
    //serverOverview->initServerOverview(*clientConnection);
    //setCentralWidget(serverOverview);
    serverOverview->initServerOverview(*clientConnection);
    centerTabViews->addTab(serverOverview,tr("ServerOverview"));
}
//disconnection from server
void MainWindow::disconnectResponse()
{
    ScopedDbConnection sdc(clientConnection->getServerAddress(),clientConnection);
    sdc.kill();
//    delete clientConnection;
//    clientConnection=NULL;
}

void MainWindow::closeServerResponse()
{
}

void MainWindow::initReplicaResponse()
{
}

void MainWindow::setReplicaResponse()
{
}

void MainWindow::setShardingResponse()
{

}
//"serverStatus" : 1
void MainWindow::serverStatusResponse()
{
//    QString connName=this->getSelectedConnection();
//    DBConnectionManager* pConnManager=DBConnectionManager::getInstance();
//    DBConnection<DBClientConnection*,BSONObj>* conn=
//            pConnManager->getConnectByName(connName.toStdString());
}

void MainWindow::selectedDatabaseChanged()
{
    try{
        QModelIndex selectedIndex=databaseExplorerView->currentIndex();
        Node* selectedNode=databaseExplorerModel->nodeFromIndex(selectedIndex);
        if(selectedNode->type==Node::Collection)
        {
            if(!bsonExplorerDockPane)
            {
                if(bsonListView==NULL )
                {
                     bsonListView=new QListView;
                }
                if(bsonListModel==NULL)
                {
                    bsonListModel=new BsonListModel;
                    connect(bsonListView,SIGNAL(clicked(QModelIndex)),bsonListModel,
                        SLOT(selectedBSONObjChanged(QModelIndex)));
                    connect(bsonListModel,SIGNAL(addBSONObjTableView(BSONObj)),
                        this,SLOT(showSelectedBOSNOBjTableView(BSONObj)));
                }
                bsonListView->setModel(bsonListModel);

                bsonExplorerDockPane=new QDockWidget(tr("BSON Explorer"),this);
                bsonExplorerDockPane->setObjectName("bsonExplorerDockPane");
                bsonExplorerDockPane->setWidget(bsonListView);
                bsonExplorerDockPane->setAllowedAreas(Qt::AllDockWidgetAreas);
                addDockWidget(Qt::LeftDockWidgetArea,bsonExplorerDockPane);
            }
            bsonListModel->setSelectedCollection(clientConnection,selectedNode->str.toStdString());

        }
    }catch(DBException& e)
    {
        cout<<__FUNCTION__<<":"<<e.what()<<"\n";
    }
}


void MainWindow::showSelectedBOSNOBjTableView(BSONObj selectedObj)
{
    static int count=0;
    count++;
    cout<<"function:"<<__FUNCTION__<<" was called "<<count<<" times..{"<<endl;
    cout<<"bsonobj="<<selectedObj<<endl;

    QTableView* bsonView=new QTableView;
    BsonExplorerModel* bsonExplorerModel=new BsonExplorerModel;
    bsonView->setModel(bsonExplorerModel);
    bsonView->setEditTriggers(QAbstractItemView::DoubleClicked);

    bsonView->setItemDelegateForColumn(0, &userIDDelegate);
    bsonExplorerModel->setBSONObject(selectedObj);
    centerTabViews->addTab(bsonView,tr("BSON%1").arg(count));

//    cout<<"selected row="<<bsonListView->currentIndex().row()<<",size="<<bsonListModel->allBSONObjs.size()<<endl;

//    int i=0;
//    try{
//        QModelIndex selectedIndex=bsonListView->currentIndex();
////        qDebug()<<"row:"<<selectedIndex.row()<<"bsonListModel->allBSONObjs.size():"<<bsonListModel->allBSONObjs.size()<<"\n";
//        BSONObj selectedObj=bsonListModel->allBSONObjs[selectedIndex.row()];
//        printBSONObj();
////        string selectedStr=bsonListModel->allNames[selectedIndex.row()];
//        QTableView* bsonView=new QTableView;
//        BsonExplorerModel* bsonExplorerModel=new BsonExplorerModel;
//        bsonView->setModel(bsonExplorerModel);
//        bsonExplorerModel->setBSONObject(selectedObj);
////        bsonExplorerModel->setBSONObject(selectedStr);
//        centerTabViews->addTab(bsonView,tr("BSON%1").arg(count));
//    }catch(...)
//    {
//        qDebug()<<"\n"<<__FUNCTION__<<" i="<<i<<"\n";
//    }
    cout<<"}"<<endl;
}

void MainWindow::printBSONObj()
{
//    for(int i=0;i<bsonListModel->allBSONObjs.size();i++)
//    {
//        cout<<"allBSONObjs["<<i<<"].md5="<<bsonListModel->allBSONObjs[i].md5()<<"\n";
//        //cout<<__FUNCTION__<<"\t"<<bsonListModel->allBSONObjs[i];
//    }
}




void MainWindow::addUserResponse()
{
    AddUserWidget* addUserWidget=new AddUserWidget();
    centerTabViews->addTab(addUserWidget,tr("Add User"));
}

void MainWindow::repairDatabaseResponse()
{
}

void MainWindow::restoreDtatbaseResponse()
{
}

void MainWindow::dropCollectionResponse()
{
    QString collName=this->getSelectedCollection();
    int ret = QMessageBox::warning(this, tr("Drop Collection"),
                                   tr("Are you sure to drop the Collection:")+(collName),
                                   QMessageBox::Ok | QMessageBox::Discard | QMessageBox::Cancel,
                                   QMessageBox::Cancel);
    switch (ret) {
       case QMessageBox::Ok:
           // Save was clicked
           break;
       case QMessageBox::Discard:
           // Don't Save was clicked
           break;
       case QMessageBox::Cancel:
           // Cancel was clicked
           break;
       default:
           // should never be reached
           break;
     }
}
void MainWindow::addDatabaseResponse()
{
    AddDatabaseDialog addDatabase(this);
    if(addDatabase.exec())
    {
        QString databaseName=addDatabase.getDatabaseName();
        if(databaseName.isEmpty())
        {
            return ;
        }
        clientConnection->insert(databaseName.toStdString(),BSONObj());
        //cout<<"databaseName:"<<bAuth<<"errmsg:"<<errmsg<<endl;
    }
}


void MainWindow::insertCollectionResponse()
{
    if(!editCollection)
    {
        editCollection=new EditCollectionWidget(this);
        connect(editCollection,SIGNAL(doInsertCollection(QString)),this,SLOT());
    }
    editCollection->show();
    editCollection->raise();
    editCollection->activateWindow();
}
void MainWindow::doCollectionInsertResponse(QString collectionContent)
{

//    QString databaseName=getSelectedDbName();
//    if(clientConnection->createCollection(databaseName.toStdString()))
//    {

//    }
//    else
//    {

//    }
}
void MainWindow::databaseOverViewResponse()
{
    BSONObj dbStats=BSON("dbStats"<<1),info;
    QString databaseName=getSelectedDb();
    clientConnection->runCommand(databaseName.toStdString(),dbStats,info,0);
    static DatabaseOverviewWidget databaseOverview(info,this);
    commandShow->addItem(tr(dbStats.toString().c_str()));
    databaseOverview.show();
}

void MainWindow::collectionStatsResponse()
{
    QString databaseName=getSelectedDb();
    QString collectionName=getSelectedCollection();
    collectionName=collectionName.remove(databaseName+".");
    BSONObj collStats=BSON("collStats"<<collectionName.toStdString()),info;

    clientConnection->runCommand(databaseName.toStdString(),collStats,info,0);
    AddTraceLine(tr(collStats.toString().c_str()));
    QTableView* collStatsTable=new QTableView;
    BsonExplorerModel* collStatsModel=new BsonExplorerModel;
    collStatsTable->setModel(collStatsModel);
    collStatsModel->setBSONObject(info);
    centerTabViews->addTab(collStatsTable,tr("Collection Stats"));
}



void MainWindow::doProfilingLevel()
{
    static ProfilingLevelDialog profilingLevelDialog;
    QString databaseName=getSelectedDb();
    mongo::DBClientWithCommands::ProfilingLevel level;
    clientConnection->getDbProfilingLevel(databaseName.toStdString(),level);

    profilingLevelDialog.SetSelectedProfiling(level);
    profilingLevelDialog.show();
}

QString MainWindow::getSelectedCollection()
{
    QModelIndex selectedIndex=databaseExplorerView->currentIndex();
    Node* selectedNode=databaseExplorerModel->nodeFromIndex(selectedIndex);
//    if(selectedNode->type==Node::Collection)
//        selectedNode=selectedNode->parent;

    return selectedNode->str;
}
MainWindow* MainWindow::pInstance=NULL;
DBClientConnection *MainWindow::getSelectedConnection()
{
    return this->clientConnection;
}

QString MainWindow::getSelectedDb()
{
    QModelIndex selectedIndex=databaseExplorerView->currentIndex();
    Node* selectedNode=databaseExplorerModel->nodeFromIndex(selectedIndex);
    if(selectedNode->type==Node::Collection ||
            selectedNode->type==Node::Javascript ||
            selectedNode->type==Node::User)
    {
        return selectedNode->parent->parent->str;
    }
    return selectedNode->str;
}

void MainWindow::dropIndex()
{
    try{
        QString dbName=getSelectedDb();
         cout<<dbName.toStdString()<<endl;
        clientConnection->dropIndexes(dbName.toStdString());
    }catch(DBException& e)
    {
         cout<<__FUNCTION__<<":"<<e.toString()<<"\n";
    }
}

void MainWindow::setPreferences()
{
    PreferencesDialog prefs(this);
            if (prefs.exec())
                    if (prefs.saveSettings())
                        emit prefsChanged();
}



void MainWindow::viewDataResponse()
{

    QString db=this->getSelectedDb();
    gridFS=new GridFS(*clientConnection,db.toStdString());
    static BsonTableViewWidget bsonTableWidget;
    bsonTableWidget.setGridFS(*gridFS);
    centerTabViews->addTab(&bsonTableWidget,tr("Bson Table"));
}

MainWindow::~MainWindow()
{
    Preferences::deleteInstance();
}

void MainWindow::doEditJavaScriptResponse()
{
    if(NULL==javaScriptEditor)
    {
        javaScriptEditor= new JsEditor(this);
        javaScriptEditor->setConnection(clientConnection);
    }
    centerTabViews->addTab(javaScriptEditor,tr("JavaScript Editor"));
    //string result=Utils::get_cmd_result("ls -l");
    //javaScriptEditor->setText(QString::fromStdString(result));
    //setCurrentFile("");
    /*
    QProcess mongostat;
    mongostat.start(tr("mongostats"));
    char str[1024]={0};
    while(mongostat.readLine(str,1024)!=-1)
    {

        javaScriptEditor->insert(tr(str));
        memset(str,0,1024);
    }
    mongostat.kill();
    */
}

void MainWindow::closeActiveWindow()
{
    if(centerTabViews->isVisible() && centerTabViews->count()>0)
    {
        centerTabViews->removeTab(centerTabViews->currentIndex());
    }
}

void MainWindow::closeTabWindow(int index)
{
    if(NULL!=centerTabViews)
    {
        centerTabViews->removeTab(index);
    }
}

void MainWindow::closeAllWindows()
{
    if(centerTabViews->isVisible() && centerTabViews->count()>0)
    {

        while(centerTabViews->count()>0)
        {
            centerTabViews->removeTab(0);
        }
    }
}

void MainWindow::renameCollectionResponse()
{
    QModelIndex& curIndex=databaseExplorerView->currentIndex();
    databaseExplorerView->setEditTriggers(QAbstractItemView::AnyKeyPressed);
    //databaseExplorerView->
}

void MainWindow::restoreCollectionResponse()
{
}

void MainWindow::shardingOptionsResponse()
{
    static ShardingWidget shardingOptionsWidget;
    centerTabViews->addTab(&shardingOptionsWidget,"Sharding Options");
}

void MainWindow::aggretationResponse()
{
    static AggregatoinWidget aggregationWidget;
    centerTabViews->addTab(&aggregationWidget,"Aggregation");
}

void MainWindow::mapReduce()
{
    qDebug("start map reduce\n");
    if(NULL==mapReduceWidget)
    {

        mapReduceWidget=new MapReduceWidget();
    }
    if(centerTabViews==NULL)
    {
        centerTabViews=new QTabWidget();
        setCentralWidget(centerTabViews);
    }
    if(centerTabViews->indexOf(mapReduceWidget)==-1)
    {
        qDebug("add map reduce...\n");
        centerTabViews->addTab(mapReduceWidget,"MapReduce");
    }
}

//void MainWindow::contextMenuEvent(QContextMenuEvent *event)
//{
//    //QPoint pos;

//    QPoint point = event->pos();
//    if(!point.isNull())
//    {
//        QMenu *menu = new QMenu();
//        menu->addSeparator();
//        menu->addSeparator();
//        menu->exec(event->globalPos());
//        delete menu;
//    }
//    event->accept();
//}

void MainWindow::SlotItemClicked(const QModelIndex& item)
{
    QModelIndex index = databaseExplorerView->currentIndex();
     Node* pNode=databaseExplorerModel->nodeFromIndex(index);
     if (qApp->mouseButtons() == Qt::LeftButton)
     { return; }
     if (qApp->mouseButtons() == Qt::RightButton)
     {
         if(index.isValid())
            showContextMenu(pNode);
         if(pNode->type==Node::Database)
         {
             AddTraceLine(tr("use ")+pNode->str);
         }
     }
}

void MainWindow::showContextMenu(Node* pNode)
{
    QMenu menu(this);
    if(pNode->type==Node::Connection)
    {
        menu.addAction(disconnectAction);
        menu.addAction(closeServerAction);
        menu.addAction(initReplicaAction);
        menu.addAction(setReplicaAction);
        menu.addAction(setShardingAction);
    }
    else if(pNode->type==Node::Database)
    {
        menu.addAction(dropDatabaseAction);
        menu.addAction(insertCollectionAction);
        menu.addAction(addUserAction);
        menu.addAction(runJSAction);
        menu.addAction(repairDatabaseAction);
        menu.addAction(initGFSAction);
        menu.addAction(restoreAction);
        menu.addAction(profilingLevelAction);
        menu.addAction(databaseOverViewAction);
    }
    else if(pNode->type==Node::Javascript)
    {
        menu.addAction(editJavascriptAction);
        //menu.addAction();
    }
    else if(pNode->type==Node::Collection)
    {
        menu.addAction(dropCollectionAction);
        menu.addAction(renameCollectionAction);
        menu.addAction(backupCollectionAction);
        menu.addAction(restoreCollectionAction);
        menu.addAction(importCollectionAction);
        menu.addAction(exportCollectionAction);
        menu.addAction(compactCollectionAction);
        menu.addAction(viewAction);
        menu.addAction(indexManageAction);
        menu.addAction(reIndexAction);
        menu.addAction(statsCollectionAction);
    }
    else if(pNode->type==Node::GridFS)
    {

    }
    else if(pNode->type==Node::Index)
    {

    }
    else if(pNode->type==Node::Connection)
    {

    }
    menu.exec(QCursor::pos());
}

void MainWindow::AddTraceLine(QString str)
{
    pTraceList->addItem(str);
}













void MainWindow::runJavaScript()
{
}
